package com.dimples.dd.xxl.job.plus.config;

import com.dimples.dd.xxl.job.plus.discovery.DiscoveryProvider;
import com.dimples.dd.xxl.job.plus.event.DiscoveryEvent;
import com.dimples.dd.xxl.job.plus.event.ServiceDownEvent;
import com.dimples.dd.xxl.job.plus.event.ServiceRefreshEvent;
import com.dimples.dd.xxl.job.plus.event.ServiceUpEvent;
import com.dimples.dd.xxl.job.plus.executor.XxlJobPlusSpringExecutor;
import com.dimples.dd.xxl.job.plus.prop.XxlJobPlusProperties;
import com.xxl.job.core.biz.ExecutorBiz;
import com.xxl.job.core.biz.impl.ExecutorBizImpl;
import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;

/**
 * 自动配置
 *
 * @author zhongyj <1126834403@qq.com><br/>
 * @date 2024/10/18
 */
@EnableConfigurationProperties(XxlJobPlusProperties.class)
@Configuration
public class XxlJobPlusAutoConfig implements ApplicationListener<DiscoveryEvent> {
    private static final Logger logger = LoggerFactory.getLogger(XxlJobPlusAutoConfig.class);

    @Autowired
    private XxlJobPlusProperties xxlJobPlusProperties;

    @Autowired
    private ApplicationContext applicationContext;

    @Autowired
    private DiscoveryProvider discoveryProvider;

    private final Object lock = new Object();

    private boolean isRunning = false;

    public XxlJobPlusAutoConfig() {
        logger.info(">>>>>>>>>>> xxl-job-plus, XxlJobPlusAutoConfig init");
    }

    @Async
    @Override
    public void onApplicationEvent(@SuppressWarnings("NullableProblems") DiscoveryEvent event) {
        synchronized (lock) {
            if (applicationContext == null) {
                logger.error("applicationContext is null, cannot get bean");
                return;
            }
            XxlJobPlusSpringExecutor xxlJobExecutor = applicationContext.getBean("xxlJobExecutor", XxlJobPlusSpringExecutor.class);
            if (event instanceof ServiceUpEvent) {
                if (!isRunning) {
                    xxlJobExecutor.start();
                }
            } else if (event instanceof ServiceDownEvent) {
                if (isRunning) {
                    xxlJobExecutor.stop();
                }
            } else if (event instanceof ServiceRefreshEvent serviceRefreshEvent) {
                if (isRunning) {
                    if (serviceRefreshEvent.getAddressList().isEmpty()) {
                        xxlJobExecutor.stop();
                    } else {
                        xxlJobExecutor.refresh(serviceRefreshEvent.getAddressList());
                    }
                } else {
                    if (!serviceRefreshEvent.getAddressList().isEmpty()) {
                        xxlJobExecutor.start();
                    }
                }
            }
            isRunning = xxlJobExecutor.getRunningStatus();
        }
    }

    @Lazy
    @Bean
    public XxlJobSpringExecutor xxlJobExecutor() {
        return new XxlJobPlusSpringExecutor(xxlJobPlusProperties, discoveryProvider);
    }

    @Lazy
    @Bean
    public ExecutorBiz executorBizImpl() {
        return new ExecutorBizImpl();
    }
}
